<script lang="ts">
import { h, defineComponent, withDirectives } from 'vue';
import { ElTable, ElTableColumn, vLoading } from 'element-plus';
import KPagination from './k-pagination.vue';
import { formatDate, formatDateTime, formatPrice, formatPriceCent, formatPriceUnit, formatPercentUnit, formatPrivateMobile } from '@/utils';
import BaseCopy from '@/components/base-copy/index.vue';
// import { mapState } from 'pinia'; // 引入映射函数

const buildInTypes: any = {
  date: formatDate, // 格式化时间： YYYY/MM/DD
  dateTime: formatDateTime, // 格式化时间： YYYY/MM/DD HH:mm:ss
  price: formatPrice,
  priceCent: formatPriceCent,
  priceUnit: formatPriceUnit,
  percent: formatPercentUnit,
  copy: (value: any) => h(BaseCopy, { value, title: '点击复制' }),
  mobile: formatPrivateMobile
  // number: kws.KWidgetNumber,
  // percent: kws.KWidgetPercent,
  // duration: kws.KWidgetDuration
};
// const isSafari = Is.safari();
export default defineComponent({
  props: {
    data: { type: Array, default: () => [] },
    columns: { type: Array, default: () => [] },
    showPagination: { type: Boolean, default: true }, // 显示分页
    pages: { type: Object, default: () => ({ total: 0 }) },
    emptyText: { type: String, default: undefined }
  },
  emits: ['selection-change', 'sort-change', 'page-change', 'size-change'],
  data() {
    return {
      selectedList: [], // 选中的数据
      sortState: {
        order: undefined,
        prop: undefined
      }
    };
  },
  computed: {
    // 没有传columns 则使用el-table原始支持的方式渲染内容
    useColumns() {
      return this.columns && this.columns.length;
    }
  },
  watch: {
    data: {
      handler() {
        this.selectedList = [];
      }
    },
    defaultSort: {
      handler(newVal) {
        this.sortState = newVal ?? {
          order: undefined,
          prop: undefined
        };
      },
      immediate: true
    }
  },
  methods: {
    /**
     *@description 表头排序点击回调
     *@return
     *@date 2023/12/12 18:18:59
     */
    handleSortChange({ prop, sortOrders }: any) {
      // 点击同一个排序项，并且该排序项只有一种排序方式 则直接返回
      if (this.sortState.prop === prop && sortOrders.length === 1) return;
      if (this.sortState.prop === prop) {
        // 如果是同一个数据切换排序方式 直接切换排序为sortOrders下一项 如果超出最后一项 切换为第一项
        const index = sortOrders.indexOf(this.sortState.order || null);
        this.sortState.order = sortOrders[index > sortOrders.length - 2 ? 0 : index + 1];
      } else {
        // 不同数据切换排序 默认为sortOrders第一项排序 目前项目为默认降序
        this.sortState.prop = prop;
        this.sortState.order = sortOrders[0];
      }
      this.$emit('sort-change', this.sortState);
    },
    renderTable() {
      const tableData = {
        ...this.$attrs,
        ref: 'kTable',
        class: 'k-table',
        data: this.data,
        emptyText: this.emptyText,
        onSelectionChange: (s: any) => {
          this.selectedList = s || [];
          this.$emit('selection-change', s);
        },
        onSortChange: (sortData: any) => {
          this.$emit('sort-change', sortData);
        }
      };

      const slots: any = {
        default: this.renderTableChildren
      };
      // 空数据插槽可自定义 / 使用默认
      const vnodes = [withDirectives(h(ElTable, tableData, slots), [[vLoading, this.$attrs.loading]])];
      if (this.$slots.suffix) {
        vnodes.push(h('div', { class: 'k-table-suffix' }, this.$slots.suffix()));
      }
      return vnodes;
    },
    renderTableChildren() {
      let children: any = [];
      if (this.useColumns) {
        children = this.columns.map(this.renderColumnItem);
      } else {
        children = this.$slots.default ? this.$slots.default() : null;
      }
      return children;
    },
    renderColumnItem(col: any) {
      // 以下是自定义属性,
      const { key, type, label, prop, align = 'left', tooltip, headerSlot, render, sortable, sortOrders, ...props } = col;
      const renderSlot = typeof render === 'string' ? render : undefined;
      const tableColumnData = {
        label,
        prop,
        align,
        key: key || prop || renderSlot,
        sortOrders,
        ...props
      };

      if (tooltip !== undefined) tableColumnData.showOverflowTooltip = tooltip;
      if (sortOrders) {
        let labelSortOrderClass = '';
        const orders = sortOrders;
        if (!orders.includes('descending')) labelSortOrderClass += ' hide-descending-icon';
        if (!orders.includes('ascending')) labelSortOrderClass += ' hide-ascending-icon';

        if (labelSortOrderClass) {
          tableColumnData.labelClassName = (tableColumnData.labelClassName || '') + labelSortOrderClass;
        }
      } else if (sortable && !sortOrders) {
        // 默认只有两种排序状态, 且先降序
        tableColumnData.sortOrders = ['descending', 'ascending'];
      }

      let contentType = '';
      if (['selection', 'index', 'expand'].includes(type)) {
        tableColumnData.type = type;
        tableColumnData.key = type;
      } else {
        contentType = type;
      }

      const slots: any = {};
      // header
      slots.header = (s: any) => {
        const { prop: sortProp, order } = this.sortState;
        const headerContentRender = [];

        if (headerSlot && this.$slots && this.$slots[headerSlot]) {
          headerContentRender.push(this.$slots[headerSlot](s));
        } else if (label) {
          headerContentRender.push(label);
        } else {
          headerContentRender.push(null);
        }
        const headerCellProps: any = {
          class: 'header-cell-wrapper '
        };
        // 添加自定义排序内容
        if (sortable) {
          headerCellProps.class += ` is-sortable  ${sortProp === prop && 'sort-active'}`;
          headerCellProps.onClick = () => this.handleSortChange(tableColumnData);
          const sortRender = h('span', { class: 'header-sort-wrapper' }, [
            h('i', { class: `k-sort-caret ascending  ${sortProp === prop && order === 'ascending' && 'active'}` }),
            h('i', { class: `k-sort-caret descending ${sortProp === prop && order === 'descending' && 'active'}` })
          ]);
          headerContentRender.push(sortRender);
        }
        return h('div', headerCellProps, headerContentRender);
      };
      // default
      slots.default = (s: any) => {
        let content = null;
        // 支持render
        if (typeof render === 'function') {
          content = render(s, col);
        } else if (renderSlot && this.$slots && this.$slots[renderSlot] !== undefined) {
          content = this.$slots[renderSlot](s);
        } else if (contentType && buildInTypes[contentType]) {
          // 应用格式化函数（只支持单个参数格式化函数）
          // 或 应用组件
          if (typeof buildInTypes[contentType] === 'function') {
            content = buildInTypes[contentType](s.row[prop]);
          } else {
            content = h(buildInTypes[contentType], { value: s.row[prop] });
          }
        } else if (prop) {
          content = s.row[prop];
        }
        return content;
      };

      return h(ElTableColumn, tableColumnData, slots);
    },
    renderPagination() {
      if (!this.showPagination || !this.pages?.total) return null;
      if (this.$slots.pagination) return this.$slots.pagination();

      const paginationData: any = {
        ref: 'kPagination',
        onPageChange: (p: number) => {
          this.$emit('page-change', p);
        },
        onSizeChange: (size: number) => {
          let currentPage = this.pages.page;
          if (this.pages.page * size > this.pages.total) {
            currentPage = 1;
          }
          this.$emit('size-change', currentPage, size);
        }
      };
      paginationData.currentPage = this.pages.page;
      paginationData.pageSize = this.pages.pageSize;
      paginationData.pageSizes = this.pages.pageSizes;
      paginationData.total = this.pages.total;
      return h(KPagination, paginationData);
    }
  },
  render() {
    const data: any = {
      class: 'k-table-box'
    };
    return h('div', data, [this.renderTable(), this.renderPagination()]);
  }
});
</script>
<style lang="scss">
// k-table-box
.k-table-box {
  --el-table-text-color: #303133;
  --el-text-color-regular: #303133;

  background-color: #fff;

  // 覆盖element table样式覆盖导致ui上的问题
  .el-table__inner-wrapper::before {
    height: 0;
  }

  // 操作
  .el-link + .el-link {
    margin-left: 16px;
  }
}

// k-table
.k-table {
  font-size: 14px;

  // color: #212533;
  color: #303133;

  .el-table__header {
    tr th.el-table__cell,
    tr th.el-table-fixed-column--left {
      padding-top: 12px;
      padding-bottom: 12px;
      font-size: 14px;
      font-weight: 600;
      line-height: 23px;
      color: #909399;
      background-color: #f5f7fa;
      border-bottom-color: #ebeef5;
    }

    // 自定义表头排序部分
    .header-cell-wrapper {
      &.is-sortable {
        cursor: pointer;
      }

      &.sort-active {
        color: var(--brand-6);
      }

      .header-sort-wrapper {
        position: relative;
        display: inline-flex;
        flex-direction: column;
        align-items: center;
        width: 8px;
        height: 14px;

        // margin-left: 2px;
        overflow: initial;
        vertical-align: middle;
        cursor: pointer;

        .k-sort-caret {
          position: absolute;
          left: 2px;
          width: 0;
          height: 0;
          border: solid 4px transparent;
          transform: scale(.75);
          transform-origin: left;

          &.ascending {
            top: -2px;
            border-bottom-color: #a8abb2;

            &.active {
              border-bottom-color: var(--brand-6);
            }
          }

          &.descending {
            bottom: 0;
            border-top-color: #a8abb2;

            &.active {
              border-top-color: var(--brand-6);
            }
          }
        }
      }
    }

    th.el-table__cell {
      &.ascending,
      &.descending {
        color: var(--brand-6);
      }

      &.ascending .sort-caret.ascending {
        border-bottom-color: var(--brand-6);
      }

      &.descending .sort-caret.descending {
        border-top-color: var(--brand-6);
      }

      &.hide-ascending-icon {
        .ascending {
          display: none;
        }
      }

      &.hide-descending-icon {
        .descending {
          display: none;
        }
      }
    }
  }

  // .el-table td.el-table__cell, .el-table th.el-table__cell.is-leaf{}

  .el-table__body {
    tr td.el-table__cell {
      padding-top: 12px;
      padding-bottom: 12px;
      line-height: 23px;
      border-bottom-color: #ebeef5;
    }

    // tr td .cell {
    //   padding-right: 16px;
    //   padding-left: 16px;
    // }
  }

  // 覆盖hover背景色
  &.el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell {
    background-color: #fbfbfb !important;
  }

  // empty
  .el-table__empty-block {
    min-height: 240px;
  }
}
</style>
